// Thud - a dynamic object-oriented language
// Copyright (C) 2009,2010 David H. Hovemeyer <david.hovemeyer@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/*
 * System_Symbol.cpp
 *
 *  Created on: Jan 8, 2010
 *      Author: dhovemey
 */

#include <cassert>
#include <cstdint>
#include <string>
#include "interp/VM_Interpreter.h"
#include "interp/VM_Object.h"

extern "C"
VM_Object* System_Symbol_toString(VM_Thread *thread, VM_ThreadOperandStack::iterator argIter, unsigned numArgs)
{
	VM_SymbolInfo *symInfo = (VM_SymbolInfo *) VM_RECEIVER->getMagicPtr();
	return VM_INTERP->getInternedVMString(symInfo->name, thread);
}

extern "C"
VM_Object* System_Symbol_equals(VM_Thread *thread, VM_ThreadOperandStack::iterator argIter, unsigned numArgs)
{
	if (numArgs != 2) {
		return VM_INTERP->getVMBoolean(false);
	}

	// because symbols are interned, a simple pointer equality test suffices
	return VM_INTERP->getVMBoolean(VM_RECEIVER == VM_METHOD_ARG(1));
}

extern "C"
VM_Object* System_Symbol_compareTo(VM_Thread *thread, VM_ThreadOperandStack::iterator argIter, unsigned numArgs)
{
	if (numArgs != 2) {
		// TODO: throw exception?
		return VM_INTERP->getNil();
	}

	int32_t cmp;
	if (!VM_INTERP->isType(VM_METHOD_ARG(1), CLASS_ID_SYMBOL)) {
		cmp = VM_INTERP->compareDifferentTypes(VM_RECEIVER, VM_METHOD_ARG(1));
	} else if (VM_RECEIVER == VM_METHOD_ARG(1)) {
		cmp = 0;
	} else {
		// lexicographical comparison by symbol name
		VM_SymbolInfo *left = (VM_SymbolInfo *) VM_RECEIVER->getMagicPtr();
		VM_SymbolInfo *right = (VM_SymbolInfo *) VM_METHOD_ARG(1)->getMagicPtr();
		cmp = left->name.compare(right->name);
	}

	return VM_INTERP->getVMInt32(cmp, thread);
}
